#include "iapsession.h"
#include "iapserver.h"
#include "clientservercommon.h"
#include "iapclientadapter.h"

#include <mw/eikappui.h>
#include <mw/apacmdln.h>
#include <mw/apgcli.h>
#include <mw/apgtask.h>
#include <mw/APGWGNAM.H>
#include <e32cmn.h>

#include <QDebug>

//http://stackoverflow.com/questions/551507/how-do-i-create-an-s60-app-that-writes-to-idle-active-screen
const TUid KSymbianIdleScreen = {0x102750F0};

TPtrC QStringToDes(QString& buf);
QString DesToQString8(const TDesC8 &buf);

CIAPSession::CIAPSession(TInt aHostAppWindow, TInt aSelfWin):
    iIsbusy(EFalse),
    iHostWin(aHostAppWindow),
    iSelfWin(aSelfWin),
    iCtrlStatus(EServiceBackground)
{
}

CIAPSession::~CIAPSession()
{
    delete iap_client;
    qDebug() << "CIAPSession::Destructor";
}

CIAPSession* CIAPSession::NewL(TInt aHostAppWindow, TInt aSelfWin)
{
    CIAPSession* self = new(ELeave) CIAPSession(aHostAppWindow, aSelfWin);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
}

void CIAPSession::ConstructL()
{
    iap_client = new (ELeave) IAPClientAdapter(*this);
    TApaTask task(CCoeEnv::Static()->WsSession());
    task.SetWgId(iHostWin);
    task.BringToForeground();
    qDebug() << "CIAPSession::ConstructL";
}

void CIAPSession::ServiceL(const RMessage2& aMessage)
{
    if(iIsbusy){
        qDebug() << "CIAPSession::ServiceL busy !!!";
        aMessage.Panic(_L("CIAPSession"), KErrServerBusy); // invoke panic on client side
        return;
    }

    iIsbusy = ETrue;
    iMessage = aMessage;

    TInt cmd = iMessage.Function();
    switch(cmd)
    {
    case EIAPServUserAndData:
    case EIAPServPurcase:
        {
        TPckgBuf<TIAPrequestData> product;
        iMessage.ReadL(0, product);
        TIAPrequestData& data = product();
        iHostWin = data.appWinGroup;
        CaptureControl();
        if(cmd == EIAPServUserAndData)
            iap_client->getUserAndDeviceId();
        else
            iap_client->purchaseProduct(DesToQString8(data.payload));
        break;
        }

    case EIAPServProductData:
        {
        TPckgBuf<TProductData> product;
        iMessage.ReadL(0, product);
        TProductData& data = product();
        iHostWin = data.appWinGroup;
        iap_client->getProductData(DesToQString8(data.productId));
        break;
        }

    default:
        qDebug() << "CIAPSession::ServiceL leave : KErrNotSupported";
        iMessage.Complete(KErrNotSupported);
        break;
    }
    qDebug() << "CIAPSession::ServiceL func : " << cmd << " iHostWin : " << iHostWin;
}

void CIAPSession::Notify(int /*requestId*/, QString aMessage)
{
    TIAPrequestData data;
    data.payload.Copy(QStringToDes(aMessage).Left(data.payload.MaxLength()));
    TPckgBuf<TIAPrequestData> product(data);

    iMessage.WriteL(0, product);
    iIsbusy = EFalse;
    giveUpControl();
}

void CIAPSession::ProductDataNotify(int /*requestId*/,
                                    QString productInformation,
                                    QString description,
                                    QString shortDescription,
                                    QString price)
{
    qDebug() << "productInformation : ";
    qDebug() << productInformation << ", "
             << description << ", "
             << shortDescription << ", "
             << price;

    TProductData data;

//    productInformation = "productInformation";
//    description = "description";
//    shortDescription = "shortDescription";
//    price = "price";

    data.productInformation.Copy(QStringToDes(productInformation).Left(data.productInformation.MaxLength()));
    data.description.Copy(QStringToDes(description).Left(data.description.MaxLength()));
    data.shortDescription.Copy(QStringToDes(shortDescription).Left(data.shortDescription.MaxLength()));
    data.price.Copy(QStringToDes(price).Left(data.price.MaxLength()));

    TPckgBuf<TProductData> product(data);

    iMessage.WriteL(0, product);
    iIsbusy = EFalse;
    giveUpControl();
}

void CIAPSession::ShowIdleScreen()
{
    qDebug() << "CIAPSession -- ShowIdleScreen";
    TApaTaskList taskList(CCoeEnv::Static()->WsSession());
    TApaTask task = taskList.FindApp(KSymbianIdleScreen);
    if (task.Exists())
        {
        qDebug() << "CIAPSession -- ShowIdleScreen done";
        task.BringToForeground();
        }
}

TPtrC QStringToDes(QString& buf)
{
    return (TPtrC(reinterpret_cast<const TUint16*>(buf.utf16())));
}

QString DesToQString8(const TDesC8 &buf)
{
    return (QString::fromLocal8Bit(reinterpret_cast<const char *>(buf.Ptr()),
                                  buf.Length()));
}


void CIAPSession::CaptureControl()
{
    iCtrlStatus = EServiceForeground;
    TApaTask task(CCoeEnv::Static()->WsSession());
    task.SetWgId(iSelfWin);
    task.BringToForeground();
}

void CIAPSession::giveUpControl()
{
    iCtrlStatus = EServiceBackground;
    iMessage.Complete(KErrNone);
    TApaTask task(CCoeEnv::Static()->WsSession());
    task.SetWgId(iHostWin);
    task.BringToForeground();
}

void CIAPSession::ClientAppFocusChanged(TInt eventCode)
{
    qDebug() << "CIAPSession::ClientAppFocusChanged eventCode: " <<
                eventCode << " iCtrlStatus: " << iCtrlStatus << " iHostWin: " << iHostWin;
    if(eventCode == EEventFocusGroupChanged){
        switch(iCtrlStatus){
            case EServiceForeground:
                {
                TApaTask task(CCoeEnv::Static()->WsSession());
                //check what is come to foreground
                if(iHostWin == CCoeEnv::Static()->WsSession().GetFocusWindowGroup()){
                    qDebug() << "CIAPSession::ClientAppFocusChanged : bring host to foreground";
                    task.SetWgId(iSelfWin);
                    task.BringToForeground();
                    }
                }
                break;
            case EServiceBackground:
                {
                qDebug() << "CIAPSession::ClientAppFocusChanged : checking whether iHostWin quits";
                TApaTask task(CCoeEnv::Static()->WsSession());
                task.SetWgId(iHostWin);
                RThread testExists;
                if(testExists.Open(task.ThreadId()) == KErrNone)
                    testExists.Close();
                else if (iHostWin != KErrNotFound){
                    qDebug() << "CIAPSession::ClientAppFocusChanged : iHostWin has exited";
                    iHostWin = KErrNotFound;
                    ShowIdleScreen();
                    }
                }
                break;
            default:
                //never comes here
                break;
        }
    }
}

